const inquirer = require("inquirer");
const ora = require("ora");
const t = require("../config/dict");
const config = require("../mfo.config.js");
const path = require("path");
const {
  exeCommand,
  exeCommandSpawn,
  error,
  stringCase,
  log,
  isWindows,
  packageManager,
} = require("./utils");
const fs = require("fs");
const prettier = require("prettier");

const uiConfig = {
  vue: {
    "element-ui": [
      {
        sign: 'import Vue from "vue";',
        replaceText: `
        import Vue from "vue";
        import ElementUI from 'element-ui';
        import 'element-ui/lib/theme-chalk/index.css';
        Vue.use(ElementUI);
        `,
      },
    ],
    "element-plus": [
      {
        sign: 'import { createApp } from "vue";',
        replaceText: `
          import { createApp } from "vue";
          import ElementPlus from 'element-plus';
          import 'element-plus/dist/index.css';
          `,
      },
      {
        sign: "const app = createApp(App);",
        replaceText: `
          const app = createApp(App);
          app.use(ElementPlus);
          `,
        qiankun: false,
      },
      {
        sign: "instance = createApp(App);",
        replaceText: `
          instance = createApp(App);
          instance.use(ElementPlus);
          `,
        qiankun: true,
      },
    ],
    "vant@latest-v2": [
      {
        sign: 'import Vue from "vue";',
        replaceText: `
          import Vue from "vue";
          import Vant from 'vant';
          import 'vant/lib/index.css';
          Vue.use(Vant);
          `,
      },
    ],
    vant: [
      {
        sign: 'import { createApp } from "vue";',
        replaceText: `
          import { createApp } from "vue";
          import { Button } from 'vant';
          import 'vant/lib/index.css';
          `,
      },
      {
        sign: "const app = createApp(App);",
        replaceText: `
          const app = createApp(App);
          app.use(Button);
          `,
        qiankun: false,
      },
      {
        sign: "instance = createApp(App);",
        replaceText: `
          instance = createApp(App);
          instance.use(Button);
          `,
        qiankun: true,
      },
    ],
    "bootstrap@3 jquery popper.js @types/jquery": [
      {
        sign: 'import Vue from "vue";',
        replaceText: `
        import Vue from "vue";
        import 'bootstrap';
        import $ from 'jquery';
        import 'bootstrap/dist/css/bootstrap.min.css';
        import 'bootstrap/dist/js/bootstrap.min.js';
        Vue.prototype.$ = $;
        `,
        config: {
          require: 'const webpack = require("webpack");',
          configureWebpack: `
            plugins: [
              // 配置 jQuery 插件的参数
              new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery",
                Popper: ["popper.js", "default"],
              }),
            ],
          `,
        },
      },
    ],
    "bootstrap jquery @popperjs/core @types/jquery": [
      {
        sign: 'import { createApp } from "vue";',
        replaceText: `
          import { createApp } from "vue";
          import 'bootstrap/dist/css/bootstrap.min.css';
          import 'bootstrap/dist/js/bootstrap.min.js';
          `,
        config: {
          require: 'const webpack = require("webpack");',
          configureWebpack: `
            plugins: [
              // 配置 jQuery 插件的参数
              new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery",
                Popper: ["popper.js", "default"],
              }),
            ],
          `,
        },
      },
    ],
  },
  react: {
    antd: [
      {
        sign: "import React from 'react';",
        replaceText: `
        import React from 'react';
        import { Button, version } from "antd";
        import 'antd/dist/reset.css';
        `,
      },
    ],
    "bootstrap jquery @popperjs/core @types/jquery": [
      {
        sign: "import React from 'react';",
        replaceText: `
          import React from 'react';
          import 'bootstrap/dist/css/bootstrap.min.css';
          import 'bootstrap/dist/js/bootstrap.min.js';
          `,
      },
    ],
  },
};

const getUICode = (pk, ui) => {
  pk = /vue/.test(pk) ? "vue" : pk;
  switch (ui) {
    case "element-ui":
      return uiConfig[pk][ui];
    case "element-plus":
      return uiConfig[pk][ui];
    case "vant@latest-v2":
      return uiConfig[pk][ui];
    case "vant":
      return uiConfig[pk][ui];
    case "bootstrap@3 jquery popper.js @types/jquery":
      return uiConfig[pk][ui];
    case "bootstrap jquery @popperjs/core @types/jquery":
      return uiConfig[pk][ui];
    case "antd":
      return uiConfig[pk][ui];
    default:
      return [];
  }
};

const configUIToProject = (metaData, ui) => {
  return new Promise((resolve, reject) => {
    const dirName = metaData.projectDir;
    const filePath = path.resolve(process.cwd(), path.join(".", dirName));
    const projectType = metaData.projectType[0].toLowerCase();
    const stack = metaData.projectTechnologyStack.toLowerCase();
    const isJs = metaData.projectDevelopLang === "javascript";
    const isVite = /vite/.test(projectType);
    let activeFile =
      filePath +
      "/src/" +
      (stack === "react"
        ? isVite
          ? "main"
          : "index"
        : /vue/.test(stack)
        ? "main"
        : "main") +
      (isJs ? ".js" : stack === "react" ? ".tsx" : ".ts");
    const codes = getUICode(stack, ui);
    if (codes.length > 0 && fs.existsSync(activeFile)) {
      let data = fs.readFileSync(activeFile, "utf-8");
      for (let i = 0; i < codes.length; i++) {
        let code = codes[i];
        i > 0
          ? code.qiankun &&
            (metaData.projectQiankun === "yes" ? true : false) === code.qiankun
            ? (data = data.replace(`${code.sign}`, `${code.replaceText}`))
            : false
          : (data = data.replace(`${code.sign}`, `${code.replaceText}`));
        if (
          /vue/.test(stack) &&
          code.config &&
          fs.existsSync(filePath + "/vue.config.js")
        ) {
          let data = fs.readFileSync(filePath + "/vue.config.js", "utf-8");
          data = [code.config.require, data].join(" ");
          data = data
            .replace(/\n|\r/gim, "")
            .replace(/\s{2,}/gim, " ")
            .replace(/configureWebpack\:\s+{(.+)},\s*}\)/gim, (a, b) => {
              b &&
                (a = a.replace(b, [b, code.config.configureWebpack].join(" ")));
              return a;
            });
          fs.writeFileSync(
            filePath + "/vue.config.js",
            prettier.format(data, {
              semi: false,
              parser: "babel",
            })
          );
        }
      }
      fs.writeFileSync(
        activeFile,
        prettier.format(data, {
          semi: false,
          parser: isJs ? "babel" : "babel-ts",
        })
      );
    }
    resolve();
  });
};

const parseUI = (context, ui, _LOCALSOURCE) => {
  const metaData = context.metadata;

  const spinner = ora(
    [t(context.lang, "安装中"), ",", metaData.projectUIType, " ..."].join(" ")
  );
  spinner.start();

  return new Promise((resolve, reject) => {
    configUIToProject(metaData, ui).then(() => {
      packageManager()
        .run(["cache", "clean", "--force"], {
          cwd: path.resolve(process.cwd(), metaData.projectDir),
        })
        .then(() => {
          const cwd = path.resolve(process.cwd(), metaData.projectDir);
          packageManager(cwd)
            .install([ui, "--save-dev"], {
              cwd,
              register: _LOCALSOURCE,
            })
            .then(() => {
              spinner.text = [
                t(context.lang, "安装"),
                metaData.projectUIType,
                t(context.lang, "成功") + t(context.lang, "。"),
              ].join(" ");
              spinner.succeed();
              log("warn", {
                message: [
                  t(context.lang, "请按官方指导方案使用"),
                  t(context.lang, "。"),
                ].join(" "),
              });
              resolve(context);
            })
            .catch((err) => {
              spinner.fail();
              log("warn", {
                message: [
                  t(context.lang, "错误") +
                    ":" +
                    t(context.lang, "安装失败") +
                    "," +
                    t(context.lang, "请稍后自行处理") +
                    " ...",
                ].join(" "),
              });
              error(err);
              resolve(context);
            });
        })
        .catch((err) => {
          spinner.fail();
          error(err);
          log("warn", {
            message: [
              t(context.lang, "错误") +
                ":" +
                t(context.lang, "安装失败") +
                "," +
                t(context.lang, "请稍后自行处理") +
                " ...",
            ].join(" "),
          });
          resolve(context);
        });
    });
  });
};

module.exports = (context) => {
  const stack = context.metadata.projectTechnologyStack.toLowerCase();
  const _LOCALSOURCE = context.source; //process.env.LOCALSOURCE || config.LOCALSOURCE;
  const uiTypeChoices = [];
  const reg = new RegExp(stack);
  for (let n in config.ui) {
    const ui = config.ui[n];
    for (let x in ui) {
      reg.test(x) &&
        uiTypeChoices.push({
          name: stringCase(n),
          value: n,
        });
    }
  }
  /* Object.keys(config.ui).forEach((n) =>
    uiTypeChoices.push({
      name: stringCase(n),
      value: n,
    })
  ); */
  if (context.metadata.projectType[0].indexOf("No UI") > -1) {
    return inquirer
      .prompt([
        {
          name: "projectUIType",
          message: t(context.lang, "安装UI组件库") + "?",
          default: "elementui",
          pageSize: uiTypeChoices.length + 2,
          type: "rawlist",
          choices: [
            ...uiTypeChoices,
            {
              name: t(context.lang, "取消"),
              value: "cancel",
            },
          ],
        },
      ])
      .then((answers) => {
        const ui =
          config.ui && answers.projectUIType !== "cancel"
            ? config.ui[answers.projectUIType][
                context.metadata.projectTechnologyStack
              ]
              ? config.ui[answers.projectUIType][
                  context.metadata.projectTechnologyStack
                ].command
              : false
            : false;
        if (ui) {
          context.metadata = {
            ...context.metadata,
            projectUIType: answers.projectUIType,
          };
          return parseUI(context, ui, _LOCALSOURCE);
        } else {
          return Promise.resolve(context);
        }
      });
  } else {
    return context;
  }
};
